既存プロジェクトに対し、TypeScript設定の厳格化を行う
ESLintとは
まずは既存プロジェクトへのESLint導入についてです。
eslint --fix
ESLintについてはこちらの記事を参考に導入しました。
既存プロジェクトのTypeScriptコンパイラの設定を厳格化
それらのエラーはコメントを使って一旦は抑制することにしました。しかし、エラーの数は200個近くあり手入力でコメントを挿入するのは大変です。そこでスクリプトを使ってエラー抑制コメントを自動挿入することにしました。エラーを抑制した後は、徐々にコメントを外してエラーを直していきます。
方針としては、以下のような流れで行っていきます。それぞれのやり方について次の段落からもう少し細かく紹介します。
ルールの厳格化とエラー出力
npx tsc --noEmit > tsc_out.txt
tsc_out.txtを開くと、以下のような内容のエラーが大量に確認できます。
src/path/file_name.ts(25,17): error TS7006: Parameter 'state' implicitly has an 'any' type.
エラーの抑制
今度は、大量に出ているエラーを抑制していきます。 TypeScriptのコンパイラでは、コメントを使って発生しているエラーを抑制することができます。今回はエラーの発生している箇所に行単位でコメントを挿入してエラーを抑制します。以下の画像にあるコードでは、コンパイラは何型が返ってくるか推定出来ないためエラーとなっています。そこでコメントを挿入することにより、このように一旦エラーを抑制していきます。
スクリプトを使ったエラーの抑制
エラーの発生している箇所は数百個あります。それらの箇所一つ一つに手作業でエラーを抑制するコメントを挿入していくのは大変です。
そこで今回はスクリプトを使って、コメントを自動挿入しました。スクリプトは、次のような処理を行います。
以下のコードはReactプロジェクトに対して、コメントを挿入してコンパイラのエラーを抑制する際に使用しました。ReactでJSXタグに挟む形でコメントを書く際は、波括弧で囲まないといけないようでした。そのためコメントを追加する一行前の末尾が > で終わっているかで条件分岐している箇所があります。
import fs from 'fs';
import uniq from 'lodash/uniq';
const readData = fs.readFileSync('tsc_out.txt');
const readDataStr = readData.toString();
const outputJson: Record< string, Array> = {};
const readDataStrs = readDataStr.split('src/app/');
readDataStrs.forEach(errorLog => {
const lineExpPattern = /(\d*,\d*)/;
const lineResult = errorLog.match(lineExpPattern);
const pathResult = errorLog.split(' ')[0].split('(')[0];
if (lineResult != null && pathResult != null) {
const lineResultNum = parseInt(lineResult[0].split(',')[0]);
const pathResultFull = 'src/app/' + pathResult;
if (pathResultFull in outputJson) {
outputJson[pathResultFull].push(lineResultNum);
outputJson[pathResultFull] = uniq(outputJson[pathResultFull]);
} else {
outputJson[pathResultFull] = [lineResultNum];
}
}
});
console.log(outputJson);
Object.entries(outputJson).forEach(([fixFilePath, fixLineArray]) => {
const readFixFile = fs.readFileSync(fixFilePath);
const readFixFileStr = readFixFile.toString();
const fixFileArray = readFixFileStr.split('\n');
fixLineArray.forEach((lineNum, index) => {
const checkInJsxTagStr = fixFileArray[lineNum + index - 2];
if (checkInJsxTagStr.endsWith('>') && !checkInJsxTagStr.endsWith('=>')) {
fixFileArray.splice(lineNum + index - 1, 0, '{/* @ts-expect-error */}');
} else {
fixFileArray.splice(lineNum + index - 1, 0, '/* @ts-expect-error */');
}
});
const fixedStr = fixFileArray.join('\n');
fs.writeFileSync(fixFilePath, fixedStr);
});
結果は以下のように表示されます。keyにあるのがエラーの発生しているファイルで、valueにある配列が行番号です。どの種類のエラーが発生しているかは扱っていません。
{
'path/to/foo.tsx': [ 9, 19, 25, 67 ],
'path/to/bar.ts': [ 8, 13 ],
'path/to/baz.ts': [ 12 ]
}
スクリプトを実行する際には以下のコマンドを利用します。
npx ts-node main.ts
200箇所くらいあったエラーを2件にまで一旦抑制することができました!